package com.foreveross.proxyip.core;

import java.lang.reflect.Field;
import java.util.Date;
import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.jamon.annotations.Argument;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.transaction.annotation.Transactional;

import redis.clients.jedis.Jedis;

import com.foreveross.proxyip.core.redis.PiRedisExecption;
import com.foreveross.proxyip.core.redis.RedisExecutor;
import com.foreveross.proxyip.core.redis.RedisManager;
import com.foreveross.proxyip.core.zk.task.strategy.CheckInTask;
import com.foreveross.proxyip.entity.BaseCodeEntity;
import com.foreveross.proxyip.infra.InstanceFactory;
import com.foreveross.proxyip.infra.base.ddd.repository.IBaseRepository;
import com.foreveross.proxyip.infra.utils.ClassUtils;
import com.foreveross.proxyip.util.LatchControl;

public class BaseCode {
	
	private Logger log = LoggerFactory.getLogger(BaseCode.class);
	
	private static BaseCode baseCode = null;
	
	public static BaseCode getInstance(){
		if(baseCode==null){
			baseCode = new BaseCode();
		}
		return baseCode;
	}
	
	private IBaseRepository baseRepository = null;
		
	private IBaseRepository getRepository(){
		if(baseRepository==null){
			baseRepository = InstanceFactory.getInstance(IBaseRepository.class,"entityHibernateRepository");
		}
		return baseRepository;
	}

	
	@Argument(name="zookeeper地址", type = "baseCode")
	public static String ZK_HOST = "192.168.1.202:2181";
	
	
	@Argument(name="每个应用下载ip的最大数", type = "baseCode")
	public static String APP_DOWNLOAD_NUM = "10000" ;
	
	@Argument(name="web跟数据库下载ip的比例", type = "baseCode")
	public static String WEB_DB_SCALE = "1:9";
	@Argument(name="zookeeper Session timeout", type = "baseCode")
	public static String ZK_SESSION_TIMEOUT = "5000";
	
//	@Argument(name="zookeeper Session timeout", type = "baseCode")
//	public static String RDS_TIMEOUT = "3600000";//redis存储对象过期的时间
//	
	
	@Argument(name="设置验证线程执行超时时间", type = "baseCode")
	public static String THREAD_EXECUTE_TIMEOUT = "200000";
	
//	public static String IP_STORE = "ip_Store";
//	
//	public static String PUBLIC_CODE = "public";
	
	
	
//	public static String SOURCE_TASK_CACHE_MAX = "10000" ;
	
	
	
	@Argument(name="下载等待的时间", type = "baseCode")
	public static String DOLOAD_WAIT_TIMEOUT = "10";
	
	
//	/**前面带RD的都是redis内存储的占位符**/
//	publicW static String PUBLIC_SOURCE_TASK = "DoloadTask";
//	
//	/**公共池下载ip缓存**/
//	public static String PUBLIC_SOURCE_CACHE = "publicSourceCache";
	//最小
	@Argument(name="公共池最小数", type = "baseCode")
	public static String PUBLIC_PROXY_MIN = "100";
	//最大
	@Argument(name="公共池最大数", type = "baseCode")
	public static String PUBLIC_PROXY_MAX = "200";
	
	@Argument(name="公共池 http 检测读取页面数据超时时间 毫秒", type = "baseCode")
	public static String PUBLIC_SO_TIMEOUT = "10000";
	//
	@Argument(name="公共池 http 检测链接超时时间 毫秒", type = "baseCode")
	public static String PUBLIC_CONNECT_TIMEOUT = "3000";
	//
	@Argument(name="检测ip线程最大ip数", type = "baseCode")
	public static String PUBLIC_THREAD_MAX_IP_COUNT = "30";
	//
	@Argument(name="ip使用次数最大阀值", type = "baseCode")
	public static String PUBLIC_MAX_USED_COUNT = "10";
	//
	
	@Argument(name="公共池检入检测ip间隔时间", type = "baseCode")
	public static String PUBLIC_IN_SEPARATION_TIME="3000";
	
	@Argument(name="公共池检出时间间隔", type = "baseCode")
	public static String PUBLIC_OUT_SEPARATION_TIME="20000";
	
	@Argument(name="公共池ip检测的验证需要的间隔时间", type = "baseCode")
	public static String PUBLIC_IP_VALIDATE_SEPARATION_TIME = "100000";
	
	@Argument(name="公共池ip存在的有效时间", type = "baseCode")
	public static String PUBLIC_IP_AVAIL_TIME = "10000000";
	
	@Argument(name="公共池验证方式 0：不验证；1：url验证；3:ping验证", type = "baseCode")
	public static String PUBLIC_PROXY_VALI_TYPE = "3";

	
	@Argument(name="每个应用最多验证那么多ip", type = "baseCode")
	public static String PUBLIC_SOURCE_NUM = "10000";
	
	@Argument(name="渠道池最小ip数", type = "baseCode")
	public static String CHANNEL_PROXY_MIN = "8";
	
	@Argument(name="渠道池最大ip数", type = "baseCode")
	public static String CHANNEL_PROXY_MAX = "20";
	
	
	@Argument(name="渠道池检测线程最大ip数", type = "baseCode")
	public static String CHANNEL_THREAD_MAX_COUNT = "20";

	
	@Argument(name="渠道池检测间隔时间", type = "baseCode")
	public static String CHANNEL_IN_SEPARATION_TIME = "1000";
	
	
	@Argument(name="公共池检出时间间隔", type = "baseCode")
	public static String CHANNEL_OUT_SEPARATION_TIME = "20000";

	
	@Argument(name="渠道池ip使用次数最大阀值", type = "baseCode")
	public static String CHANNEL_MAX_USED_COUNT = "20";

	
	@Argument(name="渠道池 http 检测读取页面数据超时时间 毫秒 ", type = "baseCode")
	public static String CHANNEL_SO_TIMEOUT = "10000";
	
	@Argument(name="渠道池 http 检测链接超时时间", type = "baseCode")
	public static String CHANNEL_CONNECT_TIMEOUT = "3000";
	
	
	@Argument(name="渠道池ip检测的验证需要的间隔时间", type = "baseCode")
	public static String CHANNEL_IP_VALIDATE_SEPARATION_TIME = "100000";
	
	
	@Argument(name="渠道池ip存在的有效时间", type = "baseCode")
	public static String CHANNEL_IP_AVAIL_TIME = "300000";
	
	
	@Argument(name="渠道池ip检出的时间需要的间隔时间", type = "baseCode")
	public static String CHANNEL_IP_OUT_SEP_TIME = "600000";


	@Argument(name="db池每次换取ip的数量", type = "baseCode")
	public static String DB_EXTRACT_NUM = "10";
	
	
	@Argument(name="db池每次检入的间隔时间", type = "baseCode")
	public static String DB_IN_SEPARATION_TIME = "10000";
	
	
	@Argument(name="db池ip存在的最大数量", type = "baseCode")
	public static String DB_PROXY_MAX =	"2000";
	//db池ip存在的最小数量
	@Argument(name="db池ip存在的最小数量", type = "baseCode")
	public static String DB_PROXY_MIN =	"1000";
	
	@Argument(name="db池验证ip的最数量", type = "baseCode")
	public static String DB_THREAD_MAX_IP_COUNT = "100";
	
	
	@Argument(name="db池每次检出的间隔时间", type = "baseCode")
	public static String DB_OUT_SEPARATION_TIME = "200000";
	
	@Argument(name="获取页面超时的时间", type = "baseCode")
	public static String DB_SO_TIMEOUT = "10000";
	
	@Argument(name="连接页面超时", type = "baseCode")
	public static String DB_CONNECT_TIMEOUT = "3000";
	
	@Argument(name="ip存在池中的有效时间", type = "baseCode")
	public static String DB_IP_AVAIL_TIME = "1000000";
	
	@Argument(name="ip检测的间隔时间", type = "baseCode")
	public static String DB_IP_VALIDATE_SEPARATION_TIME = "100000";
	
	@Argument(name="线程执行超时时间", type = "baseCode")
	public static String DB_THREAD_TIMEOUT = "1000000";
	
	@Argument(name="db池验证方式 0：不验证；1：url验证；3:ping验证", type = "baseCode")
	public static String DB_PROXY_VALI_TYPE = "3";

	@Argument(name="db池ip最大使用次数", type = "baseCode")
	public static String DB_MAX_USED_COUNT = "1";
	
	@Argument(name="db池源最大下载数量", type = "baseCode")
	public static String DB_SOURCE_NUM = "500";
	
	
	private final static LatchControl latchControl = new LatchControl(30000L);
	/**
	 * 这个方法不经常用，数据库搞坏了调用一下。
	 * @return
	 * @throws IllegalArgumentException
	 * @throws IllegalAccessException
	 */
	@Transactional
	public boolean originalData() throws IllegalArgumentException, IllegalAccessException{
		Field[] fields = this.getClass().getFields();
		for(Field field:fields){
			BaseCodeEntity code = new BaseCodeEntity();
			code.setCode("baseCode");
			code.setCreateTime(new Date());
			code.setCreateUser("cctv");
			code.setKey(field.getName());
			code.setLastTime(new Date());
			Argument ann = field.getAnnotation(Argument.class);
			log.debug(ann.name() + "=" + ann.type());
			
			code.setMessage(ann.name());
			code.setState(1);
			String value =(String)field.get(null);
			code.setValue(value);
			this.getRepository().transSave(code);
		}
		return false;
	}
	
	public void initBaseCode() throws PiRedisExecption, InterruptedException{
		try{
			latchControl.wakeupWait();
		 new RedisExecutor<Boolean>() {
				@Override
				public Boolean run() throws Exception {
					List<BaseCodeEntity> codes =getRepository().findAll(BaseCodeEntity.class);
					for(BaseCodeEntity entity:codes){
						jedis.hset(entity.getCode(),entity.getKey(), entity.getValue());
					}
					return null;
				}
			}.exec();
		}finally{
			latchControl.countDown();
		}
//		RedisManager.getInstance().getJedis().del("baseCode");
//		List<BaseCodeEntity> codes =getRepository().findAll(BaseCodeEntity.class);
//		Jedis jedis = RedisManager.getInstance().getJedis();
//		try{
//			for(BaseCodeEntity entity:codes){
//				jedis.hset(entity.getCode(),entity.getKey(), entity.getValue());
//			}
//		}catch(Exception e){
//			 e.printStackTrace();
//			 RedisManager.getInstance().getJedisPool().returnBrokenResource(jedis);
//		 }finally{
//			RedisManager.getInstance().getJedisPool().returnResource(jedis);
//		}
	}
	
	
	
	/**
	 * 做成方法，方便扩展。
	 * @param code
	 * @return
	 * @throws PiRedisExecption 
	 * @throws Exception
	 */
	public static String getValue(final String key) throws PiRedisExecption {
		try {
			latchControl.waitLatch();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return new RedisExecutor<String>() {
				@Override
				public String run() throws Exception {
					String value = jedis.hget("baseCode", key);
					if(StringUtils.isBlank(value)){
						String [] params = {"baseCode",key};
						List<BaseCodeEntity> list  = getInstance().getRepository().queryResult("from BaseCodeEntity t where t.code = ? and t.key = ?",params);
						if(list!=null&&list.size()!=0){
							BaseCodeEntity code = list.get(0);
							value = code.getValue();
							jedis.hset(code.getCode(), code.getKey(),value);
						}
					}
//					Field field = BaseCode.class.getField(key);
//					String value = (String)field.get(null);
						
					return value;
				}
			}.exec();
		
//		Jedis jedis = RedisManager.getInstance().getJedis();
//		try {
//			String value = jedis.hget("baseCode", key);
//			if(StringUtils.isBlank(value)){
//				String [] params = {"baseCode",key};
//				List<BaseCodeEntity> list  = getInstance().getRepository().queryResult("from BaseCodeEntity t where t.code = ? and t.key = ?",params);
//				if(list!=null&&list.size()!=0){
//					BaseCodeEntity code = list.get(0);
//					value = code.getValue();
//					RedisManager.getInstance().getJedis().hset(code.getCode(), code.getKey(),value);
//				}
//			}
////			Field field = BaseCode.class.getField(key);
////			String value = (String)field.get(null);
//				
//			return value;
//		} catch (Exception e) {
//			RedisManager.getInstance().getJedisPool().returnBrokenResource(jedis);
//			throw new RuntimeException(e);
//		}finally{
//			RedisManager.getInstance().getJedisPool().returnResource(jedis);
//		}
	}
	
	
	
	public static void main(String[] args) throws Exception {
		BaseCode baseCode = new BaseCode();
	}
}
